feat: Add conversation history and resume functionality#2
Conversation
- Add history package for managing conversation sessions - Create session persistence in ~/.simple-agent/sessions/ - Implement --continue flag to resume last conversation - Implement --resume flag with session picker UI - Add HistoryAgent wrapper for automatic session saving - Store sessions as JSON with full message history - Index sessions by directory path for easy retrieval - Add SessionPicker TUI component for selecting sessions - Extend Agent interface with SetMemory method - Preserve provider/model settings per session This allows users to continue conversations across sessions and maintain context when working in the same directory. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Fix type assertion for session picker (use value type instead of pointer) - Display conversation history in TUI when resuming sessions - Make -r/--resume flag work without arguments using Cobra's NoOptDefVal - Remove unnecessary 'Press Enter to continue' prompt in verbose mode - Add debug output for troubleshooting session loading - Ensure proper session restoration with correct provider/model The session picker now correctly loads selected sessions and displays the full conversation history in the TUI interface. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Fix SessionPicker.Update to use pointer receiver (*SessionPicker) This ensures state changes persist across method calls - Add error handling for crypto/rand.Read in generateRandomID Prevents potential security issues with predictable session IDs Both issues were legitimate bugs found by the Cursor auto-reviewer. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @nachoal's task —— View job PR Review: Conversation History Implementation
|
- Add visible error messages when conversation history fails to save - Log to stderr to notify users of potential data loss - Include helpful message about checking disk space and permissions - For streaming, also send error through the event stream This ensures users are aware when their conversations aren't being saved, preventing silent data loss. Addresses PR review comment about error masking data loss. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @nachoal's task —— View job PR Review: Conversation History Implementation
|
- Add read locks to GetLastSessionForPath and ListSessionsForPath - Add write lock to updatePathIndex - Prevents concurrent access issues between readers and writers - Ensures metadata consistency across concurrent operations This fixes the race condition where readers could access stale or inconsistent metadata while SaveSession was updating it. Addresses PR review comment about session metadata access without locking. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @nachoal's task —— View job PR Review: Conversation History ImplementationReviewing the conversation history and resume functionality implementation... Todo List
Code Review FeedbackCritical Issues (Must Fix)1. SessionPicker UI Completely Non-Functional 🚨File: The func (p SessionPicker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {This is a critical bug that makes the session picker completely unusable:
Fix: Change to pointer receiver: func (p *SessionPicker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {2. Potential Security Issue in Random ID Generation 🔐File: Ignoring crypto/rand errors can lead to weak session IDs: if _, err := rand.Read(b); err != nil {
// Fall back to time-based seed if crypto/rand fails
// This should be extremely rare
panic(fmt.Sprintf("crypto/rand failed: %v", err))
}While the panic approach ensures no weak IDs are generated, it's overly aggressive. Better approach: if _, err := rand.Read(b); err != nil {
return "", fmt.Errorf("failed to generate secure random ID: %w", err)
}Major Issues3. Inconsistent Error Handling in Session LoadingFile: Silent failures in for _, id := range sessionIDs {
session, err := m.LoadSession(id)
if err != nil {
continue // Silent failure
}
// ...
}This could mask serious issues. Consider logging errors or returning partial results with error information. 4. Race Condition in History AgentFile:
// Save session
ha.historyManager.SaveSession(ha.currentSession)If this fails, the conversation history is silently lost. Should at least log the error. Design & Architecture Issues5. Memory Leak in Stream InterceptionFile: Large buffer allocation without bounds checking: intercepted := make(chan StreamEvent, 100)For long conversations, this could accumulate significant memory. Consider smaller buffer or dynamic sizing. 6. File Permission SecurityFile: Session files use world-readable permissions: if err := os.WriteFile(filename, data, 0644); err != nil {Conversation history may contain sensitive information. Consider using Code Quality Issues7. Magic Numbers and Hard-coded Values
8. Timestamp Loss in Message ConversionFile: Converting from LLM messages loses original timestamps: Timestamp: time.Now(), // We don't have original timestampsThis makes conversation history less useful for debugging and analysis. Performance Considerations9. Inefficient Session SortingFile: Sessions are sorted on every request. For users with many sessions, this could be slow. Consider:
10. JSON Marshaling on Every SaveFile: Pretty-printing JSON on every save adds overhead: data, err := json.MarshalIndent(session, "", " ")For frequent saves, consider using Positive Aspects✅ Well-structured architecture - Clean separation between history management and agent logic Test Coverage AssessmentMissing Test Areas:
Recommendations
Security Recommendations
This is a solid foundation for conversation history, but the critical SessionPicker bug needs immediate attention. |
Previously, HistoryAgent was only saving the user message and final response, missing all intermediate tool calls and assistant reasoning. This fix ensures the complete agent memory is captured by syncing with GetMemory() after each query completes successfully. - Update Query method to capture full agent memory after successful completion - Update QueryStream method to capture full agent memory on EventTypeComplete - Sync session messages with agent's complete conversation history - Ensure all tool interactions are preserved for accurate session replay 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @nachoal's task —— View job PR Review: Conversation History Implementation
|

Summary
This PR adds comprehensive conversation history and resume functionality to Simple Agent Go, allowing users to continue conversations across sessions and maintain context when working in the same directory.
Key Features
1. Conversation Persistence
~/.simple-agent/sessions/2. New CLI Flags
-c/--continue: Continue the last conversation in the current directory-r/--resume: Show interactive session picker or resume specific sessionsimple-agent -r- Opens session picker UIsimple-agent -r <session-id>- Directly resume specific session3. Session Management
YYYYMMDD_HHMMSS_<6-char-random>4. Interactive Session Picker
Implementation Details
Architecture
history/package: Core types and manager for session persistenceagent.HistoryAgent: Wrapper that auto-saves after each messagetui.SessionPicker: Interactive UI component for session selectionAgentinterface withSetMemory()for restoring conversationsTechnical Improvements
NoOptDefValfor optional flag arguments-v)Testing
The implementation has been tested with:
-c-r-r <id>Example Usage
Future Enhancements
This implementation provides a solid foundation for conversation persistence while maintaining the simplicity and performance that makes Simple Agent Go successful.
🤖 Generated with Claude Code